home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Telnet / NCSA / tn3270 2.4d7 source / tn3270 / scrap.c < prev    next >
Text File  |  1992-04-17  |  20KB  |  878 lines

  1. /*
  2.  *  tn3270 for the Macintosh Source Code
  3.  *  Brown University Computing and Information Services
  4.  *  Version 2.4d7  April, 1992
  5.  *  Copyright (c) 1988, 1989, 1990, 1991, 1992 by Brown University and by
  6.  *  Peter John DiCamillo.
  7.  *
  8.  *  Permission is granted to any individual or institution to use, copy,
  9.  *  or redistribute the binary version of this software and its
  10.  *  documentation provided this notice and the copyright notices are
  11.  *  retained.  Permission is granted to any individual or non-profit
  12.  *  institution to use, copy, modify, or redistribute the source files
  13.  *  of this software provided this notice and the copyright notices are
  14.  *  retained.  This software may not be distributed for profit, either
  15.  *  in original form or in derivative works, nor can the source be
  16.  *  distributed to other than an individual or a non-profit institution.
  17.  *  Any  individual or group interested in seeing and/or using these
  18.  *  source files but who are prevented from doing so by the above
  19.  *  constraints should contact Don Wolfe, Assistant Vice-President for
  20.  *  Computer Systems at Brown University, (401) 863-7250, for possible
  21.  *  software licensing of the source developed at Brown.
  22.  *
  23.  *  Brown University and Peter John DiCamillo make no representations
  24.  *  about the suitability of this software for any purpose.
  25.  *
  26.  *  BROWN UNIVERSITY AND PETER JOHN DICAMILLO GIVE NO WARRANTY, EITHER
  27.  *  EXPRESS OR IMPLIED, FOR THE PROGRAM AND/OR DOCUMENTATION PROVIDED,
  28.  *  INCLUDING, WITHOUT LIMITATION, WARRANTY OF MERCHANTABILITY AND
  29.  *  WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE.
  30.  *
  31.  */
  32.  
  33. #if !defined(USEDUMP)
  34.     #include "maclib.h"
  35.     #include "termdef.h"
  36.     #include "tn3270funcs.h"
  37.     #include "globals.h"
  38. #else
  39.     #pragma load "tn3270DumpFile"
  40. #endif
  41.  
  42. #include "telnet.h"
  43.  
  44. #pragma segment 3270seg2
  45.  
  46. static char tableflag = 0;
  47. static char textflag = 0;
  48. static char calcflag;
  49. static long calcsize;
  50. static unsigned char * scrapptr;
  51. static unsigned char * expresult;
  52. static unsigned short * expresattr;
  53.  
  54. OSErr newscrap(cnr *cp)
  55. {
  56. long allocsize;
  57. scrapline * sp;
  58. unsigned char * chrptr;
  59. short i;
  60.  
  61. /* Return if there is already a scrap which is large enough */
  62. if ((scrapstart != 0) && (scrapwidth >= cp->cs.altcols)
  63.      && (scrapalloc >= cp->cs.altrows)) {
  64.     return(noErr);
  65.     }
  66.  
  67. /* Allocate new scrap */
  68.  
  69. if (scrapstart != 0) {
  70.     removescrap();                        /* remove scrap which is too small */
  71.                                         /* uses value of scrapalloc */
  72.     if (cp->cs.altrows > scrapalloc)    /* permanent allocation is one screen */
  73.         scrapalloc = cp->cs.altrows;
  74.     if (cp->cs.altcols > scrapwidth)
  75.         scrapwidth = cp->cs.altcols;
  76.     }
  77. else {
  78.     scrapalloc = cp->cs.altrows;
  79.     scrapwidth = cp->cs.altcols;
  80.     }
  81.     
  82. allocsize = sizeof(struct scrapline) * scrapalloc;
  83. allocsize += scrapalloc * scrapwidth * 3;        /* 1 byte for char, 2 for attrs. */
  84. allocsize += scrapwidth * 3;        /* for expresult and expresattr */
  85. scrapstart = (scrapline *)myNewPtr(allocsize, 0);
  86. if (scrapstart == 0) {
  87.     return(1);
  88.     }
  89. chrptr = (unsigned char *)scrapstart;
  90. chrptr += sizeof(struct scrapline) * scrapalloc;
  91. sp = scrapstart;
  92. for (i=0; i < scrapalloc-1; i++) {
  93.     sp->nextline = sp + 1;
  94.     sp->text = chrptr;
  95.     chrptr += scrapwidth;
  96.     sp->attr = (unsigned short *)chrptr;
  97.     chrptr += scrapwidth * 2;
  98.     sp++;
  99.     }
  100. sp->nextline = 0;
  101. sp->text = chrptr;
  102. chrptr += scrapwidth;
  103. sp->attr = (unsigned short *)chrptr;
  104. chrptr += scrapwidth * 2;
  105.  
  106. expresult = chrptr;
  107. chrptr += scrapwidth;
  108. expresattr = (unsigned short *)chrptr;
  109.  
  110. scrapsize = 0;            /* no lines in use */
  111. return(0);
  112. }
  113.  
  114. void removescrap(void)
  115. {
  116. scrapline *sp, *nextsp;
  117.  
  118. if (scrapstart == 0) {
  119.     return;
  120.     }
  121.  
  122. exportscrap(1);                /* copy private scrap to desk scrap */
  123.  
  124.                                 /* return private scrap storage */
  125. sp = scrapstart;
  126. sp += scrapalloc - 1;            /* sp -> last permanent element */
  127. nextsp = sp->nextline;            /* nextsp -> first extra element, if any */
  128. while (nextsp != 0) {            /* free each extra element */
  129.     sp = nextsp;
  130.     nextsp = sp->nextline;
  131.     DisposPtr((Ptr)sp);
  132.     }
  133. DisposPtr((Ptr)scrapstart);            /* free permanent elements */
  134. scrapstart = 0;
  135. if (pasteok && usemyscrap) {
  136.     pasteok = usemyscrap = 0;
  137.     }
  138. }
  139.  
  140. void importscrap(void)
  141. {
  142. long offset, ssize;
  143.  
  144. scrapsize = 0;                /* discard my scrap */
  145. ssize = GetScrap(0, 'TEXT', &offset);
  146. pasteok = (ssize > 0);
  147. usemyscrap = 0;
  148. }
  149.  
  150. void exportscrap(char endflag)
  151. {
  152. unsigned char * scrapmem;
  153. OSErr rc;
  154.  
  155. if (scrapsize == 0) return;    /* nothing to do if no scrap */
  156.  
  157.                             /* calculate size of exported scrap */
  158. calcsize = 0;
  159. calcflag = 1;
  160. doexport();
  161.                             /* return if size = 0 */
  162. if (calcsize == 0) return;
  163.                             /* allocate memory to hold scrap */
  164. scrapmem = (unsigned char *)myNewPtr(calcsize, 0);
  165. if (scrapmem == 0) {
  166.     beep(0);
  167.     return;
  168.     }
  169.                             /* initialize scrap */
  170. rc = ZeroScrap();
  171. if (rc != 0) {
  172.     DisposPtr(scrapmem);
  173.     beep(0);
  174.     return;
  175.     }
  176.                             /* copy data to scrap and return storage */
  177. scrapptr = scrapmem;
  178. calcflag = 0;
  179. doexport();
  180. rc = PutScrap(calcsize, 'TEXT', scrapmem);
  181. DisposPtr(scrapmem);
  182. if (rc != 0) {
  183.     beep(0);
  184.     return;
  185.     }
  186.                             /* if end call, load scrap into memory */
  187. if (endflag) LoadScrap();
  188. }
  189.  
  190. void doexport(void)
  191. {
  192. register short col;
  193. short startoff, len, colstart, colend;
  194. short linecount;
  195. char expstate, initsel, sel, anytext;
  196. scrapline * sp;
  197. scrapline currline;
  198.  
  199. sp = scrapstart;
  200. linecount = 0;
  201. anytext = 0;
  202. while (linecount < scrapsize) {
  203.     currline = *sp;    /* make local copy of current line */
  204.                     /* find first selected printable character */
  205.     colstart = 0;
  206.     initsel = 0;
  207.     while (colstart < scrapwidth) {
  208.         if ((currline.attr)[colstart] & 0x0020) {
  209.             if (((currline.text)[colstart] != 0) &&
  210.                 ((currline.text)[colstart] != 0x40) &&
  211.                 (((currline.attr)[colstart] & 0x8000) == 0)) {
  212.                 if ((initsel == 0) && textflag && anytext) expbreak();
  213.                 anytext = initsel = 1;
  214.                 break;
  215.                 }
  216.             else {
  217.                 if ((initsel == 0) && textflag) {
  218.                     expendline();
  219.                     anytext = 0;
  220.                     }
  221.                 initsel = 1;
  222.                 }
  223.             }
  224.         colstart++;
  225.         }
  226.                     /* if no printable characters, output null line */
  227.     if (colstart == scrapwidth) {
  228.         if (initsel) {
  229.             expendline();
  230.             anytext = 0;
  231.             }
  232.         linecount++;
  233.         sp = sp->nextline;
  234.         continue;
  235.         }
  236.                     /* find last printable character */
  237.     colend = scrapwidth - 1;
  238.     while (colend >= 0) {
  239.         if (((currline.attr)[colend] & 0x0020) &&
  240.             ((currline.text)[colend] != 0) &&
  241.             ((currline.text)[colend] != 0x40) &&
  242.             (((currline.attr)[colend] & 0x8000) == 0)) break;
  243.         else colend--;
  244.         }
  245.     expstate = 0;
  246.     initsel = 0;
  247.     for (col = colstart; col <= colend; col++) {
  248.         sel = ((currline.attr)[col] & 0x0020) != 0;
  249.         if (tableflag || (!initsel)) { 
  250.             sel = sel && ((currline.text)[col] != 0)
  251.                       && ((currline.text)[col] != 0x40)
  252.                       && (((currline.attr)[col] & 0x8000) == 0);
  253.             initsel = sel;
  254.             }
  255.         switch(expstate) {
  256.             case 0:                        /* before first field */
  257.                         if (sel) {
  258.                             startoff = col;
  259.                             len = 1;
  260.                             expstate = 1;
  261.                             }
  262.                         break;
  263.             case 1:                        /* within field */
  264.                         if (sel) {
  265.                             len++;
  266.                             }
  267.                         else {
  268.                             expfield(&currline, startoff, len);
  269.                             startoff = col;
  270.                             len = 1;
  271.                             expstate = 2;
  272.                             initsel = 0;
  273.                             }
  274.                         break;
  275.             case 2:                        /* between fields */
  276.                         if (sel) {
  277.                             expbreak();
  278.                             startoff = col;
  279.                             len = 1;
  280.                             expstate = 1;
  281.                             }
  282.                         else {
  283.                             len++;
  284.                             }
  285.                         break;
  286.             default:    
  287.                         break;
  288.             }
  289.         }
  290.     switch(expstate) {        /* end-of-line processing */
  291.         case 0:                        /* before first field */
  292.                     break;
  293.         case 1:                        /* within field */
  294.                     expfield(&currline, startoff, len);
  295.                     if (!textflag) expendline();
  296.                     break;
  297.         case 2:                        /* between fields */
  298.                     if (!textflag) expendline();
  299.                     break;    
  300.         default:    
  301.                     break;
  302.         }
  303.  
  304.     linecount++;
  305.     sp = sp->nextline;
  306.     }
  307. }
  308.  
  309. void expfield(scrapline *sp, short offset, short len)
  310. {
  311. short linelen;
  312. register short i;
  313. char alaflag, dcflag;
  314. scrapline currline;
  315.  
  316. currline = *sp;        /* make copy of current line */
  317. /* adjust offset and length to eliminate leading blanks, nulls, and
  318.    attributes (shouldn't happen).                                    */
  319. while (len > 0) {
  320.     if (((currline.text)[offset] == 0x00) ||
  321.         ((currline.text)[offset] == 0x40) ||
  322.         ((currline.attr)[offset] & 0x8000)) {
  323.         offset++;
  324.         len--;
  325.         }
  326.     else break;
  327.     }
  328.  
  329. /* adjust length to eliminate trailing blanks, nulls, and attributes */
  330. while (len > 0) {
  331.     if (((currline.text)[offset+len-1] == 0x00) ||
  332.         ((currline.text)[offset+len-1] == 0x40) ||
  333.         ((currline.attr)[offset+len-1] & 0x8000)) {
  334.         len--;
  335.         }
  336.     else break;
  337.     }
  338.  
  339. /* skip field if no printable characters (shouldn't happen) */
  340. if (len == 0) return;
  341.  
  342. /* copy field to buffer, handling nulls, and replacing attribute
  343.    bytes by blanks                                              */
  344. linelen = 0;
  345. dcflag = 0;
  346. alaflag = (scrap_stdfont == ALAFONT);
  347. for (i=0; i < len; i++) {
  348.     if ((currline.attr)[offset+i] & 0x8000) { 
  349.         expresult[linelen] = 0x40;
  350.         expresattr[linelen++] = (currline.attr)[offset+i];
  351.         if (alaflag) {
  352.             expresattr[linelen] &= 0xff00;
  353.             dcflag = 0;
  354.             }
  355.         }
  356.     else if ((currline.text)[offset+i] == 0x00) {
  357.         if (scrap_repnull) {
  358.             expresult[linelen] = 0x40;
  359.             expresattr[linelen++] - (currline.attr)[offset+i];
  360.             if (alaflag) {
  361.                 expresattr[linelen] &= 0xff00;
  362.                 dcflag = 0;
  363.                 }
  364.             }
  365.         }
  366.     else {
  367.         if (alaflag) {
  368.             if (alatype((currline.text)+offset+i) == 2) {    /* is a diacritic */
  369.                 expresult[linelen] = (currline.text)[offset+i];
  370.                 expresattr[linelen++] = (currline.attr)[offset+i] & 0xff00;
  371.                 dcflag = 1;
  372.                 }
  373.             else {                                        /* not a diacritic */
  374.                 if (dcflag) {
  375.                     if ((currline.text)[offset+i] != 0x40) {
  376.                         expresattr[linelen-1] |= (currline.text)[offset+i];
  377.                         }
  378.                     dcflag = 0;
  379.                     }
  380.                 else {
  381.                     expresult[linelen] = (currline.text)[offset+i];
  382.                     expresattr[linelen++] = (currline.attr)[offset+i] & 0xff00;
  383.                     }
  384.                 }
  385.             }
  386.         else {
  387.             expresult[linelen] = (currline.text)[offset+i];
  388.             expresattr[linelen++] = (currline.attr)[offset+i];
  389.             }
  390.         }
  391.     }
  392.  
  393. /* translate from EBCDIC to Mac ASCII */
  394. for (i=0; i < linelen; i++)
  395.     if (expresattr[i] & 0x4000) {        /* APL character */
  396.         expresult[i] = (*xtabh)[expresult[i] + 256];
  397.         }
  398.     else {
  399.         if (scrap_nlhandle != 0) {
  400.             expresult[i] = (*xtabh)[scrap_nltab[expresult[i]]];
  401.             }
  402.         else {
  403.             if (alaflag) {
  404.                 expresult[i] = alatrans(expresult[i], expresattr[i] & 0xff);
  405.                 }
  406.             else {
  407.                 expresult[i] = (*xtabh)[expresult[i]];
  408.                 }
  409.             }
  410.         }
  411.  
  412. /* add to the desk scrap */
  413. myPutScrap(linelen, expresult);
  414. }
  415.  
  416. unsigned char alatrans(unsigned char dc, unsigned char chr)
  417. {
  418. unsigned char *chrlist, *dclist, *dcdata;
  419. register short i;
  420. short chrindex, dcindex;
  421. unsigned char c;
  422.  
  423. if (chr == 0) return((*xtabh)[dc+512]);        /* no diacritic */
  424.  
  425. chrlist = (*alaxtabh);
  426. dclist = chrlist+16;
  427. dcdata = chrlist+32;
  428.                             /* get table index for character */
  429. chrindex = -1;
  430. for (i=0; i < 16; i++) {
  431.     if (chrlist[i] == 0) break;
  432.     if (chr == chrlist[i]) {
  433.         chrindex = i;
  434.         break;
  435.         }
  436.     }
  437.     
  438. if (chrindex < 0) return((*xtabh)[chr+512]);
  439.                             /* get table index for diacritic */
  440. dcindex = -1;
  441. for (i=0; i < 16; i++) {
  442.     if (dclist[i] == 0) break;
  443.     if (dc == dclist[i]) {
  444.         dcindex = i;
  445.         break;
  446.         }
  447.     }
  448.     
  449. if (dcindex < 0) return((*xtabh)[chr+512]);
  450.  
  451. c = dcdata[(dcindex << 4) + chrindex];
  452. if (c == 0) return((*xtabh)[chr+512]);
  453. else return(c);
  454. }
  455.  
  456. void expbreak(void)
  457. {
  458. unsigned char breakchar[1];
  459.  
  460. if (tableflag) breakchar[0] = 0x09;
  461. else breakchar[0] = 0x20;
  462. myPutScrap(1, breakchar); 
  463. }
  464.  
  465. void expendline(void)
  466. {
  467. static unsigned char endchar[1] = 0x0d;
  468.  
  469. myPutScrap(1, endchar);
  470. }
  471.  
  472. void myPutScrap(short len, unsigned char *data)
  473. {
  474. if (calcflag) {
  475.     calcsize += len;
  476.     return;
  477.     }
  478. memcpy(scrapptr, data, len);
  479. scrapptr += len;
  480. }
  481.  
  482. void scrapcut(char append, cnr *cp)
  483. {
  484. register unsigned short i, offset, a, attroff;
  485. char protfield, protflag;
  486.  
  487. tableflag = textflag = 0;
  488. scopy(append, cp);
  489.  
  490. if (!(cp->fmtscrn)) {
  491.     cp->cutflag = 1;
  492.     for (i=0; i < cp->maxcnt; i++) {
  493.         if ((cp->atrbuff)[i] & 0x0020) dselchar(i, 0, cp);
  494.         }
  495.     cp->cutflag = 0;
  496.     invldscr(cp);
  497.     return;
  498.     }
  499.  
  500. offset=firstattr(cp);
  501. cp->cutflag = 1;
  502. protflag = 0;
  503. for (i=0; i < cp->maxcnt; i++) {
  504.     a = (cp->atrbuff)[offset];
  505.     if (a & 0x8000) {        /* handle attribute byte */
  506.         protfield = (a & 0x2000) != 0;
  507.         attroff = offset;
  508.         }
  509.     if (((a & 0x8020) == 0x0020) && (!protfield)) {
  510.         dselchar(offset, attroff, cp);
  511.         }
  512.     else {
  513.         if (a & 0x0020) protflag = 1;
  514.         }
  515.     offset++;
  516.     if (offset > cp->maxoff) offset = 0;
  517.     }
  518. invldscr(cp);
  519. if (protflag) beep(cp);
  520. cp->cutflag = 0;
  521. }
  522.  
  523. void scrapcopy(char append, cnr *cp)
  524. {
  525. tableflag = textflag = 0;
  526. scopy(append, cp);
  527. }
  528.  
  529. void scrappaste(cnr *cp)
  530. {
  531. unsigned char *scrapmem;
  532. long slength, soffset;
  533. Handle shandle;
  534. short i, k, ssize;
  535. unsigned char schar;
  536.  
  537. /* get the stream of characters to paste */
  538. if (usemyscrap) {
  539.     if (scrapsize == 0) return;    /* nothing to do if no scrap */
  540.  
  541.                                 /* calculate size of exported scrap */
  542.     calcsize = 0;
  543.     calcflag = 1;
  544.     doexport();
  545.                                 /* return if size = 0 */
  546.     if (calcsize == 0) return;
  547.     ssize = calcsize;
  548.                                 /* allocate memory to hold scrap */
  549.     scrapmem = (unsigned char *)myNewPtr(calcsize, cp);
  550.     if (scrapmem == 0) {
  551.         beep(cp);
  552.         return;
  553.         }
  554.                                 /* initialize scrap */
  555.                                 /* copy data to scrap and return storage */
  556.     scrapptr = scrapmem;
  557.     calcflag = 0;
  558.     doexport();
  559.     }
  560. else {
  561.     shandle = NewHandle(0);
  562.     slength = GetScrap(shandle, 'TEXT', &soffset);
  563.     if (slength <= 0) {
  564.         beep(cp);
  565.         return;
  566.         }
  567.     scrapmem = (unsigned char *)myNewPtr(slength, cp);
  568.     if (scrapmem == 0) {
  569.         beep(cp);
  570.         return;
  571.         }
  572.     memcpy(scrapmem, *shandle, slength);
  573.     DisposeHandle(shandle);
  574.     ssize = slength;
  575.     }
  576.  
  577. if (ssize <= 0) {
  578.     DisposPtr(scrapmem);
  579.     return;
  580.     }
  581.  
  582. switch(cp->connstate) {
  583.     case 4:
  584.             break;
  585.     case 5:
  586.             break;
  587.     case 1:
  588.             if (cp->serflg) break;
  589.     default:
  590.             DisposPtr(scrapmem);
  591.             beep(cp);            /* error if wrong state for input */
  592.             return;
  593.     }
  594.  
  595. if (cp->vmxbgn && (!(cp->vmxsub))) {
  596.     DisposPtr(scrapmem);
  597.     beep(cp);            /* error if xfer mode */
  598.     return;
  599.     }
  600.  
  601.                             /* process serial line mode paste */
  602. if (cp->serflg && (cp->connstate != 5)) {
  603.     for (i = 0; i < ssize; i++) {
  604.         schar = scrapmem[i];
  605.         if (cp->servermode) {
  606.             putsrv(&schar, 1, 1, cp);
  607.             }
  608.         else {
  609.             serout(schar);
  610.             }
  611.         }
  612.     DisposPtr(scrapmem);
  613.     return;
  614.     }
  615.  
  616.                             /* process tcp server line mode paste */
  617. if ((cp->connstate != 5) && cp->servermode) {
  618.     for (i = 0; i < ssize; i++) {
  619.         schar = scrapmem[i];
  620.         putsrv(&schar, 1, 1, cp);
  621.         }
  622.     DisposPtr(scrapmem);
  623.     return;
  624.     }
  625.  
  626.                             /* tcp line mode paste */
  627. if (cp->connstate != 5) {
  628.     cp->pastebuff = myNewPtr(ssize, cp);    /* allocate buffer */
  629.     if (cp->pastebuff == 0) {
  630.         DisposPtr(scrapmem);
  631.         beep(cp);
  632.         return;
  633.         }
  634.     cp->pastebuffsize = 0;
  635.     for (i = 0; i < ssize; i++) {
  636.         schar = scrapmem[i];
  637.                             /* echo unless telnet host is doing it */
  638.         if (!(cp->hisopts)[TELOPT_ECHO]) {
  639.             putscr(&schar, 1, 0, cp);
  640.             }
  641.         if (schar > 127) continue;
  642.         (cp->pastebuff)[cp->pastebuffsize++] = schar;
  643.         }
  644.     tcpwrite(cp->pastebuff, cp->pastebuffsize, cp);
  645.     DisposPtr(cp->pastebuff);
  646.     cp->pastebuffsize = 0;
  647.     DisposPtr(scrapmem);
  648.     return;
  649.     }
  650.  
  651.                             /* 3270 mode paste */
  652. if (cp->pastebuffsize != 0) {            /* error if already doing paste */
  653.     DisposPtr(scrapmem);
  654.     beep(cp);
  655.     return;
  656.     }
  657.  
  658. if (cp->kbqsize > (KBQMAX-1)) {            /* one keyboard queue entry needed */
  659.     DisposPtr(scrapmem);
  660.     beep(cp);
  661.     return;
  662.     }
  663.  
  664. cp->pastebuff = myNewPtr(ssize, cp);    /* allocate paste queue */
  665. if (cp->pastebuff == 0) {
  666.     DisposPtr(scrapmem);
  667.     beep(cp);
  668.     return;
  669.     }
  670.             
  671.                             /* store character codes in queue */
  672. cp->pastebeep = 0;
  673. cp->pastebuffsize = 0;
  674. for (i = 0; i < ssize; i++) {
  675.     schar = scrapmem[i];
  676.     if (schar == 0x0d) k = 0xb4;  /* newline */
  677.     else if (schar == 0x09) k = 1;    /* tab -> space */
  678.     else k = (*(cp->kb_handle))[schar+640];
  679.     if (k == 0) continue;
  680.     k -= 1;
  681.     if ((kbtyp[k] & 0x0f) == 2) continue;    /* auto-key */
  682.     if (k==254) continue;                    /* overriding hex mapping */
  683.                                             /* add to queue */
  684.     (cp->pastebuff)[cp->pastebuffsize++] = k;
  685.     }
  686.                 /* put special paste  entry into keyboard queue */
  687. (cp->kbqueue)[cp->kbqsize].code = 0;
  688. (cp->kbqueue)[cp->kbqsize++].shift = 100;
  689.  
  690. DisposPtr(scrapmem);
  691. }
  692.  
  693. void scrapclear(cnr *cp)
  694. {
  695. selclear(0x00, cp);
  696. }
  697.  
  698. void scrapcopytable(char append, cnr *cp)
  699. {
  700. tableflag = 1;
  701. textflag = 0;
  702. scopy(append, cp);
  703. }
  704.  
  705. void scrapcopytext(char append, cnr *cp)
  706. {
  707. tableflag = 0;
  708. textflag = 1;
  709. scopy(append, cp);
  710. }
  711.  
  712. void scopy(char append, cnr *cp)
  713. {
  714. register short rowoff, coloff;
  715. short i;
  716. char found, scrapinit, scrapappend;
  717. scrapline * sp, *nextsp;
  718. unsigned char *chrptr;
  719. long allocsize;
  720.  
  721. scrapinit = scrapappend = 0;
  722. scrap_stdfont = cp->stdfont;
  723. scrap_nlhandle = cp->nl_handle;
  724. scrap_repnull = cp->cs.repnull;
  725. memcpy(scrap_nltab, cp->nltab, 256);
  726.  
  727. for (rowoff = 0; rowoff < cp->maxcnt; rowoff += cp->scrhsize) {
  728.     found = 0;
  729.     for (coloff = 0; coloff < cp->scrhsize; coloff++)
  730.         if ((cp->atrbuff)[rowoff+coloff] & 0x0020) {
  731.             found = 1;
  732.             break;
  733.             }
  734.     if (!found) continue;
  735.     if (!scrapinit) {        /* set sp before adding first line */
  736.         scrapinit = 1;
  737.         if (!append) scrapsize = 0;
  738.         sp = scrapstart;
  739.         if (scrapsize > 1)
  740.             for (i=0; i < scrapsize-1; i++) sp = sp->nextline;
  741.         }
  742.                             /* add new line after last line */
  743.     if (scrapsize > 0) {
  744.         if (sp->nextline == 0) {
  745.             allocsize = sizeof(struct scrapline);
  746.             allocsize += scrapwidth * 3;
  747.             sp->nextline = (struct scrapline *)myNewPtr(allocsize, cp);
  748.             if (sp->nextline == 0) {
  749.                 beep(cp);
  750.                 return;
  751.                 }
  752.             scrapappend = 1;
  753.             (sp->nextline)->nextline = 0;
  754.             chrptr = (unsigned char *)sp->nextline;
  755.             chrptr += sizeof(struct scrapline);
  756.             (sp->nextline)->text = chrptr;
  757.             chrptr += scrapwidth;
  758.             (sp->nextline)->attr = (unsigned short *)chrptr;
  759.              }
  760.         sp = sp->nextline;
  761.         }
  762.     memset(sp->text, 0, scrapwidth);
  763.     memcpy(sp->text, cp->chrbuff+rowoff, cp->scrhsize);
  764.     memset(sp->attr, 0, scrapwidth*2);
  765.     memcpy(sp->attr, cp->atrbuff+rowoff, cp->scrhsize*2);
  766.     scrapsize++;
  767.     }
  768.         /* if we saved anything, paste from our scrap */
  769. if (scrapinit) {
  770.     pasteok = usemyscrap = 1;
  771.     }
  772.  
  773.         /* return if we didn't do anything or appended new lines */
  774. if ((!scrapinit) || scrapappend) return;
  775.         /* free lines previously appended we no longer need */
  776. if (scrapsize < scrapalloc) {
  777.     sp = scrapstart;
  778.     sp += scrapalloc - 1;            /* sp -> last permanent element */
  779.     }
  780.     
  781. nextsp = sp->nextline;            /* nextsp -> first unneeded element, if any */
  782. sp->nextline = 0;                /* end chain at last element needed */
  783. while (nextsp != 0) {
  784.     sp = nextsp;
  785.     nextsp = sp->nextline;
  786.     DisposPtr((Ptr)sp);
  787.     }
  788. }
  789.  
  790. void dselchar(unsigned short start, unsigned short attroff, cnr *cp)
  791. {                                /* delete selected characters */
  792. register unsigned short src, padcount;
  793. unsigned short i, end, dest;
  794.  
  795. if (cp->fmtscrn) {    
  796.     i = cp->atrbuff[attroff];
  797.     }
  798. else i = 0;
  799.                         /* calculate last position to possibly change */
  800. if (cp->cs.repnull && cp->fmtscrn) {
  801.     if (start > 0) end = start - 1;
  802.     else end = cp->maxoff;
  803.     }
  804. else {
  805.     end = ((start / cp->scrhsize) + 1) * cp->scrhsize - 1;    /* last loc. on line */
  806.     }
  807.  
  808. src = dest = start;
  809. padcount = 0;
  810. while (1) {
  811.     if ((cp->atrbuff)[src] & 0x8000) {
  812.         break;
  813.         }
  814.     if ((cp->atrbuff)[src] & 0x0020) {
  815.         padcount++;
  816.         }
  817.     else {
  818.         newchar(dest, (cp->chrbuff)[src], (cp->atrbuff)[src], i, cp);
  819.         dest++;
  820.         if (dest == cp->maxcnt) dest = 0;
  821.         }
  822.     if (src == end) break;        /* exit if just did the last one */
  823.     src++;
  824.     if (src == cp->maxcnt) src = 0;
  825.     } 
  826. while (padcount > 0) {
  827.     newchar(dest, 0x00, 0, i, cp);
  828.     dest++;
  829.     if (dest == cp->maxcnt) dest = 0;
  830.     padcount--;
  831.     }
  832. newwrite(cp);
  833. if (cp->fmtscrn) (cp->atrbuff)[attroff] |= 0x0100;    /* set MDT bit */
  834. }
  835.  
  836. void selclear(unsigned char fillchar, cnr *cp)
  837. {
  838. register unsigned char prot;
  839. register short a, attroff, i;
  840. char changeflag;
  841.  
  842. if (cp->kblock) {
  843.     beep(cp);
  844.     return;
  845.     }
  846. changeflag = 0;
  847. if (cp->fmtscrn) a = firstattr(cp);
  848. else a = 0;
  849. for (i=0; i < cp->maxcnt; i++) {
  850.     if ((cp->atrbuff)[a] & 0x8000) {                /* attribute */
  851.         prot = ((cp->atrbuff)[a] & 0x2000) != 0;
  852.         attroff = a;        /* save attribute offset */
  853.         }
  854.     else if (cp->fmtscrn) {                /* character, formatted screen */
  855.         if (((cp->atrbuff)[a] & 0x0020) && (!prot)) {
  856.             newchar(a, fillchar, 0, (cp->atrbuff)[attroff], cp);
  857.             (cp->atrbuff)[attroff] |= 0x0100;        /* set MDT bit */
  858.             changeflag = 1;
  859.             }
  860.         }
  861.     else {                            /* character, unformatted screen */
  862.         if ((cp->atrbuff)[a] & 0x0020) {
  863.             newchar(a, fillchar, 0, 0, cp);
  864.             changeflag = 1;
  865.             }
  866.         }
  867.     a++;
  868.     if (a == cp->maxcnt) a = 0;
  869.     }
  870. if (changeflag) {
  871.     newwrite(cp);
  872.     }
  873. else {
  874.     beep(cp);
  875.     kerr(1, cp);
  876.     }
  877. }
  878.